package com.sunny.原子性.AtomicReference原子性引用.AtomicReferenceFieldUpdater原子性引用的升级;

import com.sunny.anotation.ThreadSafe;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

@Slf4j
@ThreadSafe
public class AtomicReferenceFieldUpdateTest {
    //AtomicIntegerFieldUpdater 原子性的更新某一个类的实例的指定的某一个字段
    //并且该字段由volatile进行修饰同时不能被static修饰
    //有些网上说而且不能被private修饰？下文将进行验证： 经过检测，不必须是
    private static AtomicIntegerFieldUpdater<AtomicReferenceFieldUpdateTest> updaterInteger =
            AtomicIntegerFieldUpdater.newUpdater(AtomicReferenceFieldUpdateTest.class, "count");

    // 测试String类型：经过检测，可以
    private static AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdateTest, String> updateString =
            AtomicReferenceFieldUpdater.newUpdater(AtomicReferenceFieldUpdateTest.class, String.class, "sum");

    // 测试是否必须使用volatile: 经过检测，必须是
    private static AtomicIntegerFieldUpdater<AtomicReferenceFieldUpdateTest> updaterVolatile;

    // 测试是否必须使用private：经过检测，不必须是
    private static AtomicIntegerFieldUpdater<AtomicReferenceFieldUpdateTest> updaterPrivate =
            AtomicIntegerFieldUpdater.newUpdater(AtomicReferenceFieldUpdateTest.class, "number");

    @Getter
    public volatile int count = 100;

    @Getter
    public int age = 100;

    @Getter
    public volatile String sum = "100";

    @Getter
    private volatile int number = 100;

    public static void main(String[] args) {

        AtomicReferenceFieldUpdateTest example5 = new AtomicReferenceFieldUpdateTest();

        // 测试AtomicIntegerFieldUpdater
        try{
            if (updaterInteger.compareAndSet(example5, 100, 120)) {
                log.info("updaterInteger success 1, {}", example5.getCount());
            }

            if (updaterInteger.compareAndSet(example5, 100, 120)) {
                log.info("updaterInteger success 2, {}", example5.getCount());
            } else {
                log.info("updaterInteger failed, {}", example5.getCount());
            }
        } catch (Exception e) {
            log.info("exception: updaterInteger{}", e);
        }
        System.out.println("----------------<<<<<<<<>>>>>>>>>>>------------");
        // 测试AtomicReferenceFieldUpdater
        try{
            if(updateString.compareAndSet(example5, "100", "120")) {
                log.info("updateString success 1, {}", example5.getSum());
            }
            if (updateString.compareAndSet(example5, "100", "120")) {
                log.info("updateString success 2, {}", example5.getSum());
            } else {
                log.info("updateString failed, {}", example5.getSum());
            }
        } catch (Exception e) {
            log.info("exception: updateString{}", e);
        }
        System.out.println("----------------<<<<<<<<>>>>>>>>>>>------------");
        // 测试是否必须使用volatile
        try{
            updaterVolatile = AtomicIntegerFieldUpdater.newUpdater(AtomicReferenceFieldUpdateTest.class, "age");

            if(updaterVolatile.compareAndSet(example5, 100, 120)) {
                log.info("updaterVolatile success 1, {}", example5.getAge());
            }
            if (updaterVolatile.compareAndSet(example5, 100, 120)) {
                log.info("updaterVolatile success 2, {}", example5.getAge());
            } else {
                log.info("updaterVolatile failed, {}", example5.getAge());
            }
        } catch (Exception e) {
            log.info("exception: updaterVolatile{}", e);
        }
        System.out.println("----------------<<<<<<<<>>>>>>>>>>>------------");
        // 测试是否必须使用private
        try{
            if(updaterPrivate.compareAndSet(example5, 100, 120)) {
                log.info("updaterPrivate success 1, {}", example5.getNumber());
            }
            if (updaterPrivate.compareAndSet(example5, 100, 120)) {
                log.info("updaterPrivate success 2, {}", example5.getNumber());
            } else {
                log.info("updaterPrivate failed, {}", example5.getNumber());
            }
        } catch (Exception e) {
            log.info("exception: updaterPrivate{}", e);
        }
    }
}
